home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / sudo-1.000 / sudo-1 / sudo-1.2 / logging.c < prev    next >
C/C++ Source or Header  |  1993-12-05  |  9KB  |  440 lines

  1. /*
  2.  *  sudo version 1.1 allows users to execute commands as root
  3.  *  Copyright (C) 1991  The Root Group, Inc.
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 1, or (at your option)
  8.  *  any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  If you make modifications to the source, we would be happy to have
  20.  *  them to include in future releases.  Feel free to send them to:
  21.  *      Jeff Nieusma                       nieusma@rootgroup.com
  22.  *      3959 Arbol CT                      (303) 447-8093
  23.  *      Boulder, CO 80301-1752             
  24.  * 
  25.  ****************************************************************
  26.  *
  27.  *  logging.c
  28.  *
  29.  *  this file supports the general logging facilities
  30.  *  if you want to change any error messages, this is probably
  31.  *  the place to be...
  32.  *
  33.  *  Jeff Nieusma   Thu Mar 21 23:39:04 MST 1991
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40. #include <sys/param.h>
  41. #include <sys/stat.h>
  42. #include <sys/errno.h>
  43. #include "sudo.h"
  44.  
  45. #ifdef LINUX
  46. #include <signal.h>
  47. #endif /* LINUX */
  48.  
  49. void log_error();
  50. void readchild();
  51. static void send_mail();
  52. static void reapchild();
  53. static int appropriate();
  54.  
  55. static char logline[MAXLOGLEN+8];
  56.  
  57. /**********************************************************************
  58.  *
  59.  *  log_error()
  60.  *
  61.  *  This function attempts to deliver mail to ALERTMAIL and either
  62.  *  syslogs the error or writes it to the log file
  63.  */
  64.  
  65. void log_error( code )
  66. int code;
  67. {
  68. char cwd[MAXPATHLEN+1];
  69. int argc;
  70. char **argv;
  71. register char *p;
  72. register int count;
  73. #ifndef SYSLOG
  74. register FILE *fp;
  75. time_t now;
  76. #else
  77. register int pri;           /* syslog priority */
  78. #endif
  79.  
  80.  
  81.  
  82. /*  there is no need to log the date and time twice if using syslog */
  83.  
  84. #ifndef SYSLOG 
  85. now=time ( (time_t) 0 );
  86. sprintf( logline, "%19.19s : %8.8s : ", ctime (&now), user );
  87. #else
  88. sprintf( logline, "%8.8s : ", user );
  89. #endif
  90.  
  91. p = logline + strlen(logline);  /* we need a pointer to the end of logline */
  92. getwd(cwd);                     /* so we know where we are... */
  93.  
  94. switch ( code ) {
  95.  
  96.     case ALL_SYSTEMS_GO:
  97.         sprintf ( p, "PWD=%s ; COMMAND=", cwd );
  98. #ifdef SYSLOG
  99.     pri=Syslog_priority_OK;
  100. #endif
  101.         break;
  102.  
  103.     case VALIDATE_NO_USER:
  104.         sprintf ( p, "user NOT in sudoers ; PWD=%s ; COMMAND=", cwd );
  105. #ifdef SYSLOG
  106.     pri=Syslog_priority_NO;
  107. #endif
  108.     break;
  109.  
  110.     case VALIDATE_NOT_OK: 
  111.         sprintf ( p, "command not allowed ; PWD=%s ; COMMAND=", cwd );
  112. #ifdef SYSLOG
  113.         pri=Syslog_priority_NO;
  114. #endif
  115.     break;
  116.     
  117.     case VALIDATE_ERROR:
  118.     sprintf ( p, "error in %s ; PWD=%s ; command: ", SUDOERS, cwd );
  119. #ifdef SYSLOG
  120.         pri=Syslog_priority_NO;
  121. #endif
  122.     break;
  123.  
  124.     case GLOBAL_NO_PW_ENT:
  125.         sprintf ( p, "There is no /etc/passwd entry for uid %d.  ", uid );
  126. #ifdef SYSLOG
  127.         pri=Syslog_priority_NO;
  128. #endif
  129.         break;
  130.  
  131.     case PASSWORD_NOT_CORRECT:
  132.         sprintf ( p, "%d incorrect passwords ; PWD=%s ; COMMAND=", 
  133.             TRIES_FOR_PASSWORD, cwd );
  134. #ifdef SYSLOG
  135.         pri=Syslog_priority_NO;
  136. #endif
  137.     break;
  138.  
  139.     case GLOBAL_NO_HOSTNAME:
  140.     strcat ( p, "This machine does not have a hostname " );
  141. #ifdef SYSLOG
  142.         pri=Syslog_priority_NO;
  143. #endif
  144.     break;
  145.  
  146.     case NO_SUDOERS_FILE:
  147.         switch ( errno ) {
  148.             case ENOENT:
  149.                 sprintf ( p, "There is no %s file.  ", SUDOERS );
  150.                 break;
  151.             case EACCES:
  152.                 sprintf ( p, "%s needs to run setuid root.  ", Argv[0] );
  153.                 break;
  154.             default:
  155.                 sprintf ( p, "There is a problem opening %s ", SUDOERS );
  156.             break;
  157.             }
  158. #ifdef SYSLOG
  159.         pri=Syslog_priority_NO;
  160. #endif
  161.         break;
  162.  
  163.     case GLOBAL_HOST_UNREGISTERED:
  164.         sprintf ( p, "gethostbyname() cannot find host %s ", host );
  165. #ifdef SYSLOG
  166.         pri=Syslog_priority_NO;
  167. #endif
  168.         break;
  169.  
  170.     default:
  171.     strcat ( p, "found a wierd error : ");
  172. #ifdef SYSLOG
  173.         pri=Syslog_priority_NO;
  174. #endif
  175.     break;
  176.  
  177.     }
  178.   
  179.  
  180. /* if this error is from load_globals() don't put  argv in the message */
  181. if ( ! ( code & GLOBAL_PROBLEM ) ) {
  182.  
  183.     strcat ( logline, cmnd );  /* stuff the command into the logline */
  184.     strcat ( logline, " ");
  185.  
  186.     argc = Argc-2;
  187.     argv = Argv; argv++;
  188.     p = logline + strlen(logline);
  189.     count =  (int)(logline + MAXLOGLEN - p);
  190.  
  191.     /* now stuff as much of the rest of the line as will fit */
  192.     while ( count > 0 && argc-- ) {
  193.     strncpy ( p, *++argv, count );
  194.         strcat ( p, " ");
  195.     p += 1 + (count < strlen(*argv) ? count : strlen(*argv) );
  196.     count =  (int)(logline + MAXLOGLEN - p);
  197.     }
  198.     if ( count <= 0 )            /*  if the line is too long, */
  199.     strcat ( p, " ... " );   /*  add an elipsis to the end */
  200.  
  201.     }
  202.  
  203. if ( appropriate(code) )
  204.     send_mail();
  205.  
  206. #ifdef SYSLOG
  207.  
  208. openlog ( Syslog_ident, Syslog_options, Syslog_facility );
  209. syslog ( pri, logline );
  210. closelog();
  211.  
  212. #else
  213.  
  214. if ( (fp = fopen ( LOGFILE, "a" )) == NULL )  {
  215.     sprintf ( logline, "Can\'t open log file: %s", LOGFILE );
  216.     send_mail();
  217.     }
  218. else {
  219.     fprintf ( fp, "%s\n", logline );
  220.     (void) fclose (fp);
  221. }
  222.  
  223.  
  224. #endif
  225.  
  226. }
  227.  
  228.  
  229.  
  230.  
  231. /**********************************************************************
  232.  *
  233.  *  send_mail()
  234.  *
  235.  *  This function attempts to mail to ALERTMAIL about the sudo error
  236.  *
  237.  */
  238.  
  239. char *exec_argv[]= { "sendmail" ,
  240.              "-t" ,
  241.              ALERTMAIL ,
  242.                      (char *) NULL };
  243.  
  244.  
  245. static void send_mail()
  246. {
  247. char *mailer=MAILER;
  248. char *subject=MAILSUBJECT;
  249. int fd[2];
  250. char buf[MAXLOGLEN+1024];
  251.  
  252. if ( (mailer = find_path ( mailer )) == NULL ) {
  253.     fprintf (stderr, "%s not found\n", mailer );
  254.     exit (1);
  255.     }
  256.  
  257. signal ( SIGCHLD, reapchild );
  258.  
  259. if ( fork () ) return;
  260.  
  261. /* we don't want any security problems ... */
  262. if ( setuid ( uid ) ) {
  263.     perror("setuid(uid)");
  264.     exit(1);
  265.     }
  266.  
  267. signal ( SIGHUP, SIG_IGN );
  268. signal ( SIGINT, SIG_IGN );
  269. signal ( SIGQUIT, SIG_IGN );
  270.  
  271. if ( pipe(fd) ) {
  272.     perror( "send_mail: pipe" );
  273.     exit ( 1 );
  274.     }
  275.  
  276. (void) dup2 ( fd[0], 0 );
  277. (void) dup2 ( fd[1], 1 );
  278. (void) close (fd[0]);
  279. (void) close (fd[1]);
  280.  
  281. if ( ! fork () ) {
  282.  
  283.  
  284.     /*      child                                parent     */
  285.  
  286.     (void) close(1);
  287.     execv ( mailer, exec_argv );
  288.     /* this should not happen */
  289.     perror( "execv");
  290.     exit (1);
  291.  
  292.     }
  293.  
  294. else {
  295.  
  296.                                  (void) close(0);
  297.  
  298.                                  /* feed the data to sendmail */
  299.                                  sprintf (buf, "To: %s\nSubject: %s\n\n%s\n\n", 
  300.                                      ALERTMAIL, subject, logline );
  301.                                  write ( 1, buf, strlen(buf));
  302.                                  close ( 1 );
  303.  
  304.                                  exit ( 0 );
  305.     }
  306.  
  307. }
  308.  
  309.  
  310.  
  311.  
  312.  
  313. /****************************************************************
  314.  *
  315.  *  reapchild()
  316.  *
  317.  *  This function gets rid fo all the ugly zombies
  318.  */
  319.  
  320. static void reapchild ()
  321. {
  322. (void) wait ( NULL );
  323. }
  324.  
  325.  
  326.  
  327.  
  328.  
  329. /**********************************************************************
  330.  *
  331.  *  inform_user ()
  332.  *
  333.  *  This function lets the user know what is happening 
  334.  *  when an error occurs
  335.  */
  336.  
  337. void inform_user( code )
  338. int code;
  339. {
  340.  
  341. switch ( code ) {
  342.  
  343.     case VALIDATE_NO_USER:
  344.     fprintf( stderr,
  345.           "%s is not in the sudoers file.  This incident will be reported.\n\n",
  346.         user );
  347.     break;
  348.  
  349.     case VALIDATE_NOT_OK: 
  350.     fprintf( stderr, 
  351.         "Sorry, user %s is not allowed to execute %s\n\n",
  352.         user, cmnd );
  353.     break;
  354.     
  355.     case VALIDATE_ERROR:
  356.     fprintf( stderr, 
  357.         "Sorry, there is a fatal error in the sudoers file.\n\n" );
  358.     break;
  359.  
  360.     case GLOBAL_NO_PW_ENT:
  361.         fprintf ( stderr, 
  362.         "Intruder Alert!  You don\'t exist in the passwd file\n\n");
  363.     break;
  364.  
  365.     case GLOBAL_NO_HOSTNAME:
  366.     fprintf ( stderr, 
  367.         "This machine does not have a hostname\n\n" );
  368.     break;
  369.  
  370.     case GLOBAL_HOST_UNREGISTERED:
  371.         fprintf ( stderr, 
  372.             "This machine is not available via gethostbyname()\n\n");
  373.         break;
  374.  
  375.     case PASSWORD_NOT_CORRECT:
  376.         fprintf ( stderr, "Password not entered correctly after %d tries\n\n", 
  377.         TRIES_FOR_PASSWORD );
  378.     break;
  379.  
  380.     default:
  381.     fprintf ( stderr, 
  382.         "Something wierd happened.\n\n" );
  383.     break;
  384.  
  385.     }
  386.  
  387. }
  388.  
  389.  
  390.  
  391.  
  392.  
  393. /****************************************************************
  394.  *
  395.  *  appropriate()
  396.  *
  397.  *  This function determines whether to send mail or not...
  398.  */
  399.  
  400. static int appropriate( code )
  401. int code;
  402. {
  403.  
  404. switch ( code ) {
  405.  
  406. /*  these will NOT send mail  */
  407.  
  408.     case VALIDATE_OK: 
  409.     case PASSWORD_NOT_CORRECT:
  410. /*  case ALL_SYSTEMS_GO:               this is the same as OK */
  411.         return (0);
  412.     break;
  413.  
  414.     case VALIDATE_NO_USER:
  415. #ifdef SEND_MAIL_WHEN_NO_USER
  416.     return (1);
  417. #else
  418.     return (0);
  419. #endif
  420.     break;
  421.  
  422.     case VALIDATE_NOT_OK:
  423. #ifdef SEND_MAIL_WHEN_NOT_OK
  424.     return (1);
  425. #else
  426.     return (0);
  427. #endif
  428.     break;
  429.  
  430. /*  these WILL send mail  */
  431.  
  432.     case VALIDATE_ERROR: 
  433.     case NO_SUDOERS_FILE:
  434.     default:
  435.     return (1);
  436.     break;
  437.  
  438.     }
  439. }
  440.